
/****************************************************************************
**
** Copyright (C) 2004-2008 VATATA.com . All rights reserved.
**
** This file is the part of the Miniutil Poject of VATATA.com.
** Vatata's miniutil library is lightweight and portable (for linux
** and Windows). The C++ Class Library included Threadpool, Dll danymic loading, 
** General socket application model and tcp server, httpserver/servlet, etc. 
** It is a pratical utility disigned for who don't want learn the Big C++ 
** Developing Platform, such as  Boost or ACE.
**
** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file.  Alternatively you may (at
** your option) use any later version of the GNU General Public
** License if such license has been publicly approved by VATATA.com.
** (or its successors, if any) and the Miniutil Project Aministrators. 
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://www.gnu.org/licenses/lgpl.html. If you are unsure which 
** license is appropriate for your use, please review the following 
** information: http://code.google.com/p/miniutil/ or contact 
** http://www.vatata.com.
**
** In addition, as a special exception, VATATA.com, as the sole
** copyright holder for Miniutil Project, grants users of VATATA
** P2P Platform the right to release and package with the related 
** libraries without the source code.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. vatata reserves all rights not expressly
** granted herein.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/



#include <stdio.h>

#include <iostream>
#include <stdlib.h>

#include "miniutil/log.h"
#include "miniutil/module.h"
#include "miniutil/srtti.h"
#include "miniutil/logservice.h"

using namespace miniutil;

logger::logger(unsigned long levelsin)
{
	this->levels = levelsin;
}

void logger::do_snprintf( char * str, size_t len , const char * fmt, va_list v )
{
#ifdef WIN32
	_vsnprintf(str, len - 1, fmt, v );
#else
	vsnprintf( str, len - 1 , fmt, v );
#endif
    str[len-1] = 0;
}

void logger::log(int level, const char * fmt, ... )
{
	char str[16384];

	va_list v;
	va_start( v, fmt );

    do_snprintf( str, 16380, fmt, v );

	va_end( v );

	//printf( str );

//#ifdef WIN32
//    if ( level == logger::LOG_LEVEL_ERROR )
//    {
//        
//    }
//#endif
    if(miniutil::frame::galoggservice.IsRunning())
    {
        std::string logmsg = std::string("[tag:console]")+str;
        miniutil::frame::galoggservice.log(level, logmsg);
    }
    else
    {
	    miniutil::auto_lock loglock( logmtx );
	    std::cout << str << std::flush;
    }

}

void logger::config( miniutil::tinyxml::TiXmlElement * _config )
{
	if ( _config == NULL )
		return;

	std::string value;
	this->levels = 0;
	if ( _config->QueryValueAttribute("all", &value ) == miniutil::tinyxml::TIXML_SUCCESS && value == "true" )
	{
		//this->log(LOG_LEVEL_WARN, "enable log all messages\n");
		this->levels = LOG_LEVEL_ALL;
		return;
	}

	if ( _config->QueryValueAttribute("error", &value ) == miniutil::tinyxml::TIXML_SUCCESS && value == "true" )
	{
			this->enableLevel( LOG_LEVEL_ERROR );
	}
	
	if ( _config->QueryValueAttribute("crit", &value ) == miniutil::tinyxml::TIXML_SUCCESS && value == "true" )
	{
			this->enableLevel( LOG_LEVEL_CRIT );
	}
	
	if ( _config->QueryValueAttribute("warn", &value ) == miniutil::tinyxml::TIXML_SUCCESS && value == "true" )
	{
			this->enableLevel( LOG_LEVEL_WARN );
	}
	
	if ( _config->QueryValueAttribute("debug", &value ) == miniutil::tinyxml::TIXML_SUCCESS && value == "true" )
	{
			this->enableLevel( LOG_LEVEL_DEBUG );
	}
	
	if ( _config->QueryValueAttribute("trace", &value ) == miniutil::tinyxml::TIXML_SUCCESS && value == "true" )
	{
			this->enableLevel( LOG_LEVEL_TRACE );
	}
	
	if ( _config->QueryValueAttribute("audit", &value ) == miniutil::tinyxml::TIXML_SUCCESS && value == "true" )
	{
			this->enableLevel( LOG_LEVEL_AUDIT );
	}
	
}

#ifdef _DEBUG
logger * miniutil::plog = new logger( logger::LOG_LEVEL_ALL );
#else
logger * miniutil::plog = new logger( logger::LOG_LEVEL_ERROR | logger::LOG_LEVEL_CRIT );
#endif


void miniutil::config_logger( miniutil::tinyxml::TiXmlElement * _config )
{
	if ( _config == NULL )
		return;

	miniutil::srtti::module::load( _config );

	miniutil::tinyxml::TiXmlElement *p_logger_ele = _config->FirstChildElement("logger");
	if ( p_logger_ele != NULL )
	{
		std::string classname;
		p_logger_ele->QueryValueAttribute( "classname", &classname );
		if ( classname.length() > 0 )
		{
			miniutil::logger * p_logger = (miniutil::logger *)miniutil::srtti::srtti::_newInstance( classname.c_str() ) ;
			if ( p_logger != NULL )
				plog = p_logger;
                //miniutil::local_logger_manager::default_logger = p_logger;
		}
	}

	miniutil::tinyxml::TiXmlElement * p_logger_config = _config->FirstChildElement("config");
	if ( p_logger_config != NULL )
		plog->config( p_logger_config );
}

miniutil::logger_fileflags * miniutil::logger_fileflags::p_instance = new miniutil::logger_fileflags() ;

int miniutil::logger_fileflags::init(const std::string &key, int * p_flag )
{
    miniutil::auto_lock lk( this->map_mutex );
    this->flag_map[ key ] = p_flag ;
    * p_flag = 1;
    return * p_flag ;
}

bool miniutil::logger_fileflags::isEnable( const std::string & key )
{
    miniutil::auto_lock lk( this->map_mutex );
    std::map< std::string, int *>::iterator it = this->flag_map.find( key );
    if ( it == flag_map.end() ) 
        return false;
    if ( it->second == NULL )
        return false;
    if ( *(it->second) == 0 )
        return false;
    return true;
}

bool miniutil::logger_fileflags::enable(  const std::string & key  )
{
    miniutil::auto_lock lk( this->map_mutex );
    std::map< std::string, int *>::iterator it = this->flag_map.find( key );
    if ( it == flag_map.end() ) 
        return false;
    if ( it->second == NULL )
        return false;

     *(it->second) = 1;
     return true;
}

void miniutil::logger_fileflags::disable( const std::string & key )
{
    miniutil::auto_lock lk( this->map_mutex );
    std::map< std::string, int *>::iterator it = this->flag_map.find( key );
    if ( it == flag_map.end() ) 
        return ;
    if ( it->second == NULL )
        return ;

    *(it->second) = 0;
}

using namespace miniutil::util;

miniutil::logger * miniutil::util::autoentry_logger::p_autoentry_logger = miniutil::plog;

//--------------------------------------
miniutil::util::autoentry_logger::autoentry_logger(const char* fn, const char* func, int line)
{
	sfn = fn;
	sfunc = func;
	mline = line;
#ifdef WIN32
	threadid = GetCurrentThreadId();
#else
	threadid = pthread_self();
#endif
	MLOG_TRACE(p_autoentry_logger, "[%u](%s:%s:%d)Process Enter\n", threadid ,fn, func, line);
}

miniutil::util::autoentry_logger::~autoentry_logger()
{
	MLOG_TRACE(p_autoentry_logger, "[%u](%s:%s:%d)Process Leave\n", threadid,  sfn.c_str(), sfunc.c_str(), mline);
}
